package com.guaoran.interview.in2018.jvm;

import com.sun.java.accessibility.util.AccessibilityEventMonitor;
import com.sun.nio.zipfs.ZipFileStore;

import java.util.concurrent.AbstractExecutorService;

/**
 * @author : guCheng
 * @title : JVM
 * @Description :
 * 1.JVM的内存结构，JVM的算法；
 * 2.强引用，软引用和弱引用的区别
 * 3.数组在内存中如何分配；
 * 4.请写一段栈溢出、堆溢出的代码；
 * @date :2018年3月10日下午8:08:40
 */
public class JVM {
    /**
     * 一、JVM的内存结构，JVM的算法；
     * 1.JVM的内存结构
     * 	1.JVM内存空间包含：方法区、java堆、java栈、本地方法栈。
     * 	2.方法区是各个线程共享的区域，存放类class信息、常量、静态变量。
     * 	3.java堆也是线程共享的区域，我们的类的实例就放在这个区域,new出来的对象.堆是先进先出。
     * 	4.java栈是每个线程私有的区域，它的生命周期与线程相同，一个线程对应一个java栈.而栈是先进后出。
     * 	5.PC寄存器是用于存储每个线程下一步将执行的JVM指令，如该方法为native的，则PC寄存器中不存储任何信息
     * 	6.本地方法栈JVM采用本地方法堆栈来支持native方法的执行，此区域用于存储每个native方法调用的状态
     * 2.堆：分成新生代和老年代；
     * 	1.新生代：eden+s0+s1（s0和s1大小一样，相互对称）
     * 	2.老年代：tenured
     * 3.垃圾收集算法：JVM的GC算法：GC的对象是堆空间和永久区
     * 	1.（java没用）引用计数法：当一个对象被引用时，会计数加一，不被对象引用时被回收。缺点：影响对象，很难处理循环引用。
     * 	2.标记清除法(老年代使用)：适用于存活对象较多的场合。标记和清除。缺点：标记和清除过程的效率都不高，标记清除之后会产生大量不连续的内存碎片，
     * 		空间碎片太多可能会导致，当程序在以后的运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
     * 	3.标记压缩(老年代使用) ：适用于存活对象较多的场合。标记完后移动，
     * 	4.复制算法(新生代使用)：不适合对象多的场合，将内存空间分成两块，将存活的放到另一块中，每次只能使用一块。
     * 		缺点：存活对象多的时候，会影响效率，空间浪费
     * 4.垃圾收集器
     * 	1.串行收集器：新生代使用复制算法，老年代使用标记压缩；效率高，最稳定，可能产生长时间的停顿，
     * 	2.并行收集器：新生代使用并行回收：复制算法，老年代使用串行回收；多线程，多核性能好，
     * 	3.CMS收集器：新生代使用并行收集器，老年代使用并发标记清除；并发收集、低停顿  ，不过产生大量空间碎片、并发阶段会降低吞吐量
     *
     */
    /**
     * 二、强引用，软引用和弱引用的区别
     * 	1.强引用:宁愿堆溢出也不回收的
     * 	2.软引用:如果还有内存空间，就一定不会回收，
     * 	3.弱引用:发现对象就回收
     */
    /**
     * 三、数组在内存中如何分配；
     * 	int [] arr = new int[4];
     * 在栈中创建arr数组， new出的数组放到堆中，arr数组去引用放在堆中的数组
     */
    /**
     * 四、请写一段栈溢出、堆溢出的代码；
     */
    public static void main(String[] args) {
        //classLoad 双亲委派
        System.out.println(AbstractExecutorService.class.getClassLoader());
        System.out.println(ZipFileStore.class.getClassLoader());
        System.out.println(AccessibilityEventMonitor.class.getClassLoader());
//        //GC 的方式
//        System.gc();
//        Runtime.getRuntime().gc();
    }

}
// 内部类
class Outer {
    class Inner {
    }

    public static void foo() {
//        new Inner();
    }

    public void bar() {
        new Inner();
    }

    public static void main(String[] args) {
        new Outer().new Inner();
    }
}
